namespace MoreLinq;

using System;
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// Represents a union over list types implementing either <see
/// cref="ICollection{T}"/> or <see cref="IReadOnlyCollection{T}"/>,
/// allowing both to be treated the same.
/// </summary>

readonly struct CollectionLike<T>
{
    readonly ICollection<T>? rw;
    readonly IReadOnlyCollection<T>? ro;

    public CollectionLike(ICollection<T> collection)
    {
            this.rw = collection ?? throw new ArgumentNullException(nameof(collection));
            this.ro = null;
        }

    public CollectionLike(IReadOnlyCollection<T> collection)
    {
            this.rw = null;
            this.ro = collection ?? throw new ArgumentNullException(nameof(collection));
        }

    public int Count => this.rw?.Count ?? this.ro?.Count ?? 0;

    public IEnumerator<T> GetEnumerator() =>
        this.rw?.GetEnumerator() ?? this.ro?.GetEnumerator() ?? Enumerable.Empty<T>().GetEnumerator();
}

static class CollectionLike
{
    public static CollectionLike<T>? TryAsCollectionLike<T>(this IEnumerable<T> source) =>
        source switch
        {
            null => throw new ArgumentNullException(nameof(source)),
            ICollection<T> collection => new(collection),
            IReadOnlyCollection<T> collection => new(collection),
            _ => null
        };
}
